/**
 * useEffect
 *    概念：使用副作用
 *    什么叫副作用：比如操作真实DOM、调用接口、消息订阅、全局事件的绑定... 都是副作用。就是不纯
 *    这些副作用相关的代码都不能直接放在组件顶层使用。因为组件是会更新的，一旦更新的话，这些代码会多次执行。
 *
 *    语法：
 *      基本语法：
 *        useEffect(effect[, deps])
 *          1. effect 就是副作用函数
 *             该函数默认会触发一次，后续如果 deps 声明的数据发生变化之后，该函数会再次触发
 *          2. deps   依赖数组，可不传递，但是推荐传递更好
 *
 *      清理（收尾）
 *        useEffect(effect[, deps])
 *          1. 在 effect 中，返回一个函数，该函数叫做清理函数，该清理函数会在第一次之后，每次effect触发之前先触发。
 *          使用场景：
 *            1. 当我们在 effect 中做了消息订阅、全局事件绑定、计时器定时器相关操作时，需要处理清理函数
 *                该清理函数就类似于在类组件中 componentWillUnmount 需要干的事情。
 *
 *    特点：
 *      1. deps 可以不传，不传递时，该 effect 会默认触发一次，且会在组件任意数据(state、props)更新之后都触发。
 *      2. effect 默认触发的时机是 组件挂载完成，可以基于这个特点，模拟 componentDidMount
 *          useEffect(() => {
 *          }, [])
 *      3. 模拟 componentDidUpdate()
 *          useEffect(() => {
 *          })
 *      4. 模拟 componentWillUnmount()
 *          useEffect(() => {
 *            return () => {
 *            }
 *          })
 *      5. 模拟 监听watch
 *          useEffect(() => {
 *
 *          }, [要watch的数据])
 *
 */

import { useState, useEffect } from "react";

function Hello(props) {
  const [count, setCount] = useState(1);
  const [sex, setSex] = useState("男");
  useEffect(() => {
    console.log("Hello Effect");
  }, [count, props.name]);

  return (
    <div>
      <h4>Hello</h4>
      <button onClick={() => setCount((count) => count + 1)}>{count}</button>
      <button onClick={() => setSex((sex) => (sex === "男" ? "女" : "男"))}>
        {sex}
      </button>
    </div>
  );
}

function App() {
  const [num, setNum] = useState(1);
  const [name, setName] = useState("张三");
  console.log("App render");

  // num 如果变化，会导致 该 effect 再次触发
  //     该 effect 内部可以获取到 最新的数据，原因是它的触发时候是在组件更新完成之后。
  // useEffect(() => {
  //   console.log("effect", num);
  // }, [num]);

  // useEffect(() => {
  //   console.log("effect");

  //   // 返回一个函数，做为清理函数
  //   return () => {
  //     console.log("clear");
  //   };
  // }, [num]);

  // useEffect(() => {
  //   // 这里没做 清理操作，当 num 发生变化时，这一段 setInterval 会触发多次，会有问题
  //   setInterval(() => {
  //     console.log("111");
  //   }, 1000);
  // }, [num]);

  // useEffect(() => {
  //   const timer = setInterval(() => {
  //     console.log("111");
  //   }, 1000);

  //   // 返回清理函数
  //   return () => {
  //     clearInterval(timer);
  //   };
  // }, [num]);

  useEffect(() => {
    console.log("effect");
  });

  return (
    <div>
      <h1>App</h1>
      <button onClick={() => setNum((prevNum) => prevNum + 1)}>{num}</button>
      <button onClick={() => setName((prevName) => prevName + "~")}>
        {name}
      </button>

      <hr />
      <Hello name={name} />
    </div>
  );
}

export default App;
